package com.meeting.y.util;

import com.google.common.geometry.S2CellId;
import com.google.common.geometry.S2LatLng;
import junit.framework.TestCase;

import java.util.logging.Logger;

public class S2Util extends TestCase {
    private static Logger logger = Logger.getLogger(S2Util.class.getName());

    public S2CellId getCellID(double lat,double lng){
        S2LatLng s2LatLng  = S2LatLng.fromDegrees(lat, lng);
        S2CellId celId = S2CellId.fromLatLng(s2LatLng);
        return celId;
    }
    /**
     * 经纬度 转 CellId
     */
    public void testGetCellid(){
        double lat = 22.629164;
        double lng =114.025514 ;
        for(int i=0;i<10;i++) {
            lat += lat + 0.000001;
            lng += lng + 0.000001;
            S2CellId celId = getCellID(lat, lng);

            logger.info(celId.level() + "-" + celId.id() + "-"+Long.toBinaryString(celId.id())+"-" + celId.toPoint() + "-" + celId.toToken() + "-"
                    + celId.hashCode() + "-" + celId.toString() + "-");
        }
    }


    /*
    *



CellId 转 经纬度

val s2LatLng = new S2CellId(celId).toLatLng
val lat = s2LatLng.latDegrees()
val lng = s2LatLng.lngDegrees()
S2计算距离

val startS2: S2LatLng = S2LatLng.fromDegrees(55.8241, 137.8347)
val endS2: S2LatLng = S2LatLng.fromDegrees(55.8271, 137.8347)
val dis = startS2.getEarthDistance(endS2)

经纬度构建任意形状

经纬度构建S2矩形

val startS2: S2LatLng = S2LatLng.fromDegrees(0.8293, 72.004) //左下角
val endS2: S2LatLng = S2LatLng.fromDegrees(55.8271, 137.8347) //右上角
val rect: S2LatLngRect = new S2LatLngRect(startS2, endS2)

经纬度构建S2多边形

val vertices = new util.ArrayList[S2Point]
//注意，一般需要多边形内侧，此处需要按照逆时针顺序添加。
vertices.add(S2LatLng.fromDegrees(lat, lng).toPoint)
val s2Loop = new S2Loop(vertices)
val polygon = new S2Polygon(s2Loop)

经纬度构建圆形

 double radius = 600.5; //半径
 val capHeight = (2 * S2.M_PI) * (radius / 40075017)
 S2LatLng s2LatLng= S2LatLng.fromDegrees(lat, lng);
 S2Cap cap = S2Cap.fromAxisHeight(s2LatLng.toPoint(),capHeight × capHeight / 2);

任意形状内所有S2块

val rect //构建的形状
val coverer: S2RegionCoverer = new S2RegionCoverer
coverer.setMaxLevel(7)
coverer.setMinLevel(7)
val list: util.ArrayList[S2CellId] = coverer.getCovering(rect).cellIds()

判断点是否在任意形状内

 val rect //构建的形状
 S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
 boolean contains = rect.contains(s2LatLng.toPoint());

S2块包含的S2子块

求level=7的S2块下的level=8的4个子块的S2CellId，如下：

val s2CellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(55.130666,88.700062)).parent(7)
val interval = (s2CellId.childEnd().id() - s2CellId.childBegin().id()) / 4
val childrenId = (0 until 4).flatMap(i => {
  val id = s2CellId.childBegin().id() + interval * i
  val cellId = new S2CellId(id).toLatLng
  List(cellId.lngDegrees(), cellId.latDegrees()).mkString(",")
}).mkString(";")

求level=7的S2块下的level=9的16个子块的S2CellId，如下：

val s2CellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(55.130666,88.700062)).parent(7)
val chilren = childrenCellId(s2CellId, 7, 9)


求当前cellId下的所有 子cellId
@param s2CellId 当前cellId
@param curLevel 当前cellId的level 需与cellId保持一致
@param desLevel 目标cellId的level 需大于当前cellId
@return
    def childrenCellId(s2CellId: S2CellId, curLevel:Int, desLevel:Int): List[S2CellId] = {
        if (curLevel < desLevel) {
            val interval = (s2CellId.childEnd().id() - s2CellId.childBegin().id()) / 4
            (0 until 4).flatMap(i => {
                    val id = s2CellId.childBegin().id() + interval * i
                    val cellId = new S2CellId(id)
                    childrenCellId(cellId, curLevel + 1, desLevel)
            }).toList
        } else List(s2CellId)
    }
    判断当前cellId的level

    private static int getLevel(long input) {
        int n = 0;
        while (input % 2 == 0) {
            input = input / 2;
            n++;
        }
        return 30 - n / 2;
    }

    * */
}
